#include <linux/module.h>
#include <linux/slab.h>
#include <linux/sched.h>
#include <asm/uaccess.h>  
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <linux/list.h>

struct list_head *st=NULL;
struct d_list {
        char inf;
        struct list_head list;
};

char popst(void)
{
        struct d_list *tmp=NULL;
        char ch;
        tmp = list_first_entry (st, struct d_list, list);
        ch = tmp->inf;
        list_del(&(tmp->list));      
        kfree(tmp);
        return ch;
}

void pushst(char inf)
{
        struct d_list *prob=NULL;  
        prob=(struct d_list*)kmalloc(sizeof(struct d_list), GFP_KERNEL);
        prob->inf = inf;
        list_add(&(prob->list), st);        
}



ssize_t stack_read(struct file *file, char __user *buffer, size_t count, loff_t *offset)
{
char ch;
        if (!list_empty(st))
        {ch=popst();                
                put_user(ch, buffer);
                return 1;
                 }       
        else 
        {   return 0;}
}

ssize_t stack_write(struct file *file, const char __user *buffer, size_t count, loff_t *offset)
{
       int i;
       char cmd_l;
        printk("number_of_symbols %i\n", count);
        for(i=0; i < count; i++)
        {
                get_user(cmd_l, buffer+i);
                pushst(cmd_l);
        }                               
        return count;
}

const struct file_operations stack_fops = { 
.read = stack_read,
.write = stack_write,
.owner = THIS_MODULE
};

static struct miscdevice stack_dev = {
.minor = MISC_DYNAMIC_MINOR,
.name = "stack",
.fops = &stack_fops
};

static int  ds_init()
{
       int valb;
        valb = misc_register(&stack_dev);
         if (valb != 0) {   
        return valb;
        }        
        st=(struct list_head*)kmalloc(sizeof(struct list_head), GFP_KERNEL);        
        if(st==0)
        {
                return -1;
        }
        INIT_LIST_HEAD(st);
       return 0;
}    

static void ds_exit()
{
        misc_deregister(&stack_dev);
}

module_init (ds_init);
module_exit (ds_exit);
